package garin.parse.sql;

import garin.parse.Token;
import garin.parse.io.SetValueObserver;
import garin.parse.io.Source;
import garin.parse.sql.sql2003.SqlStatement;
import garin.parse.sql.sql2003.StatementEndToken;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class SqlStatementReader implements SetValueObserver {
	private final Source source;
	private long start;
	private long end;
	protected final SqlStatementReaderClient client;
	private final Class<? extends SqlStatement> clz;
	
	public SqlStatementReader(final Source s,
			final Class<? extends SqlStatement> clz,
			final SqlStatementReaderClient client) throws Exception {
		source = s;
		this.client = client;
		this.clz = clz;
	}
	
	public void onSetValue(final Token token) throws IOException {
		if (token instanceof StatementEndToken) {
			end = source.at();
			final String value = source.contents(start, end);
			start = end++;
			client.onEndStatement(value);
		}
	}
	
	public void process() throws NoSuchMethodException, InstantiationException,
			IllegalAccessException, InvocationTargetException, Exception {
		final Constructor<? extends SqlStatement> constructor = clz
				.getConstructor(Source.class);
		source.setValueObserver(this);
		final SqlStatement stmt = constructor.newInstance(source);
		stmt.init();
		source.read(stmt);
		stmt.exit();
	}
}
